package com.music.note_android.ui.editor

import android.graphics.Color

/**
 * 基于点的绘画数据模型
 * 替代传统的线条绘制，使用点阵来表示绘画内容
 * 这样可以确保在任何缩放级别下都能保持一致的视觉效果
 */
data class PointDrawing(
    /**
     * 绘画的唯一标识符
     */
    val id: String,
    
    /**
     * 绘画工具类型
     */
    val tool: DrawingTool,
    
    /**
     * 绘画颜色
     */
    val color: Int,
    
    /**
     * 基础点大小（像素）
     * 这个大小不会随画布缩放而改变，始终保持相对于屏幕的固定大小
     */
    val basePointSize: Float,
    
    /**
     * 绘画点列表
     * 每个点都包含位置、压感等信息
     */
    val points: List<DrawingPoint>,
    
    /**
     * 创建时间戳
     */
    val timestamp: Long,
    
    /**
     * 透明度 (0.0-1.0)
     */
    val alpha: Float = 1.0f
) {
    
    /**
     * 检查绘画是否为空
     */
    fun isEmpty(): Boolean = points.isEmpty()
    
    /**
     * 获取绘画的边界矩形
     */
    fun getBounds(): android.graphics.RectF {
        if (points.isEmpty()) {
            return android.graphics.RectF(0f, 0f, 0f, 0f)
        }
        
        var minX = Float.MAX_VALUE
        var minY = Float.MAX_VALUE
        var maxX = Float.MIN_VALUE
        var maxY = Float.MIN_VALUE
        
        points.forEach { point ->
            val radius = point.getEffectiveRadius(basePointSize)
            minX = minOf(minX, point.x - radius)
            minY = minOf(minY, point.y - radius)
            maxX = maxOf(maxX, point.x + radius)
            maxY = maxOf(maxY, point.y + radius)
        }
        
        return android.graphics.RectF(minX, minY, maxX, maxY)
    }
    
    /**
     * 添加新点，返回新的PointDrawing实例
     */
    fun addPoint(point: DrawingPoint): PointDrawing {
        return copy(points = points + point)
    }
    
    /**
     * 添加多个点，返回新的PointDrawing实例
     */
    fun addPoints(newPoints: List<DrawingPoint>): PointDrawing {
        return copy(points = points + newPoints)
    }
    
    /**
     * 获取点的总数
     */
    fun getPointCount(): Int = points.size
    
    /**
     * 获取绘画的总长度（所有点之间的距离之和）
     */
    fun getTotalLength(): Float {
        if (points.size < 2) return 0f
        
        var totalLength = 0f
        for (i in 1 until points.size) {
            totalLength += points[i-1].distanceTo(points[i])
        }
        return totalLength
    }
    
    /**
     * 平移绘画
     */
    fun translate(dx: Float, dy: Float): PointDrawing {
        return copy(
            points = points.map { it.translate(dx, dy) }
        )
    }
    
    /**
     * 缩放绘画坐标（注意：点大小不会缩放）
     */
    fun scale(scaleX: Float, scaleY: Float, pivotX: Float = 0f, pivotY: Float = 0f): PointDrawing {
        return copy(
            points = points.map { it.scale(scaleX, scaleY, pivotX, pivotY) }
        )
    }
    
    /**
     * 旋转绘画
     */
    fun rotate(angle: Float, pivotX: Float = 0f, pivotY: Float = 0f): PointDrawing {
        return copy(
            points = points.map { it.rotate(angle, pivotX, pivotY) }
        )
    }
    
    companion object {
        /**
         * 创建空的点绘画
         */
        fun createEmpty(
            id: String,
            tool: DrawingTool,
            color: Int,
            basePointSize: Float
        ): PointDrawing {
            return PointDrawing(
                id = id,
                tool = tool,
                color = color,
                basePointSize = basePointSize,
                points = emptyList(),
                timestamp = System.currentTimeMillis()
            )
        }
        
        /**
         * 从传统的Stroke转换为PointDrawing
         */
        fun fromStroke(stroke: Stroke): PointDrawing {
            val drawingPoints = stroke.points.map { strokePoint ->
                DrawingPoint(
                    x = strokePoint.x,
                    y = strokePoint.y,
                    pressure = strokePoint.pressure,
                    timestamp = strokePoint.timestamp,
                    size = strokePoint.size,
                    tilt = strokePoint.tilt,
                    orientation = strokePoint.orientation
                )
            }
            
            return PointDrawing(
                id = stroke.id,
                tool = stroke.tool,
                color = stroke.color,
                basePointSize = stroke.width,
                points = drawingPoints,
                timestamp = stroke.timestamp,
                alpha = stroke.alpha
            )
        }
    }
}

/**
 * 绘画点数据模型
 * 基于StrokePoint，但专门用于点阵绘制
 */
data class DrawingPoint(
    /**
     * 点的X坐标（画布坐标系）
     */
    val x: Float,
    
    /**
     * 点的Y坐标（画布坐标系）
     */
    val y: Float,
    
    /**
     * 压感值（0.0-1.0）
     */
    val pressure: Float,
    
    /**
     * 点的创建时间戳（毫秒）
     */
    val timestamp: Long,
    
    /**
     * 触摸面积大小（可选）
     */
    val size: Float = 0f,
    
    /**
     * 点的倾斜角度（可选，弧度制）
     */
    val tilt: Float = 0f,
    
    /**
     * 点的方向角度（可选，弧度制）
     */
    val orientation: Float = 0f
) {
    
    /**
     * 计算到另一个点的距离
     */
    fun distanceTo(other: DrawingPoint): Float {
        val dx = x - other.x
        val dy = y - other.y
        return kotlin.math.sqrt(dx * dx + dy * dy)
    }
    
    /**
     * 计算到指定坐标的距离
     */
    fun distanceTo(targetX: Float, targetY: Float): Float {
        val dx = x - targetX
        val dy = y - targetY
        return kotlin.math.sqrt(dx * dx + dy * dy)
    }
    
    /**
     * 获取有效的点半径（考虑压感）
     */
    fun getEffectiveRadius(baseSize: Float): Float {
        val pressureFactor = pressure.coerceIn(0.3f, 1.0f)
        return (baseSize * pressureFactor) / 2f
    }
    
    /**
     * 平移点
     */
    fun translate(dx: Float, dy: Float): DrawingPoint {
        return copy(x = x + dx, y = y + dy)
    }
    
    /**
     * 缩放点坐标
     */
    fun scale(scaleX: Float, scaleY: Float, pivotX: Float = 0f, pivotY: Float = 0f): DrawingPoint {
        val newX = pivotX + (x - pivotX) * scaleX
        val newY = pivotY + (y - pivotY) * scaleY
        return copy(x = newX, y = newY)
    }
    
    /**
     * 旋转点
     */
    fun rotate(angle: Float, pivotX: Float = 0f, pivotY: Float = 0f): DrawingPoint {
        val cos = kotlin.math.cos(angle)
        val sin = kotlin.math.sin(angle)
        
        val dx = x - pivotX
        val dy = y - pivotY
        
        val newX = pivotX + dx * cos - dy * sin
        val newY = pivotY + dx * sin + dy * cos
        
        return copy(x = newX.toFloat(), y = newY.toFloat())
    }
    
    /**
     * 检查点是否在指定边界内
     */
    fun isInBounds(left: Float, top: Float, right: Float, bottom: Float): Boolean {
        return x >= left && x <= right && y >= top && y <= bottom
    }
    
    companion object {
        /**
         * 创建默认的绘画点
         */
        fun createDefault(x: Float, y: Float): DrawingPoint {
            return DrawingPoint(
                x = x,
                y = y,
                pressure = 1.0f,
                timestamp = System.currentTimeMillis()
            )
        }
        
        /**
         * 从StrokePoint转换
         */
        fun fromStrokePoint(strokePoint: StrokePoint): DrawingPoint {
            return DrawingPoint(
                x = strokePoint.x,
                y = strokePoint.y,
                pressure = strokePoint.pressure,
                timestamp = strokePoint.timestamp,
                size = strokePoint.size,
                tilt = strokePoint.tilt,
                orientation = strokePoint.orientation
            )
        }
    }
}